package design.create.singleton;

import java.io.Serializable;

/**
 * 懒汉式: 第一次使用时,才创建对像
 * 注: 该方式需要注意多线程同步的问题
 *
 * @author zxs
 * @since 2020/05/21
 */
public class LazySingleton implements Serializable {

    /**
     * 因为 new LazySingleton() 这个操作不是原子性的
     * 1.为对像分配内存空间
     * 2.初始化对像的参数
     * 3.将引用指向将内存地址
     * 因为jvm存在指令重排,所以实际执行的顺序可能是 132,在jdk1.5之后,提供是volatile关键字,可以禁用指令重排
     */
    private static volatile LazySingleton singleton = null;

    private LazySingleton() {
    }

    /**
     * 同步方法
     */
    public synchronized static LazySingleton getInstance1() {
        if (singleton == null) {
            singleton = new LazySingleton();
        }
        return singleton;
    }

    /**
     * 双重同步块
     */
    public static LazySingleton getInstance2() {
        LazySingleton ls = singleton;
        if (ls == null) {
            synchronized (LazySingleton.class) {
                ls = singleton;
                if (ls == null) {
                    ls = new LazySingleton();
                    singleton = ls;
                }
            }
        }
        return singleton;
    }

    /**
     * 静态内部类
     * 缺点: 不能传参
     */
    private static class LazySingletonHolder {
        private static LazySingleton singleton = new LazySingleton();
    }

    public static LazySingleton getInstance3() {
        return LazySingletonHolder.singleton;
    }

    public Object readResolve() {
        return singleton;
    }

}
